#ifndef CPOINT_H
#define CPOINT_H

#include <stdlib.h>
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;

enum CPOINT_COORDENATES {X,Y,Z};

template <typename _TO, int _SIZE = 2>
class CPoint {
	typedef _TO  value_t;
protected:
	vector<value_t> _coordenate;
	
public:
	CPoint (const value_t& _x = NULL, const value_t& _y = NULL) {
		_coordenate.push_back(_x); 
		_coordenate.push_back(_y); 
	}

	~CPoint (void){
	}

	void clear() {
		_coordenate.clear();
		_coordenate.push_back(NULL);
		_coordenate.push_back(NULL);
	}

	bool operator == (const CPoint& p){
		return _coordenate[X] == p._coordenate[X] && _coordenate[Y] == p._coordenate[Y];
	}

	CPoint& operator+= (const CPoint& p){
		_coordenate[0] += p._coordenate[0];
		_coordenate[1] += p._coordenate[1];
		return *this;
	}


	CPoint& operator/= (const CPoint& p){
		_coordenate[0] /= p._coordenate[0];
		_coordenate[1] /= p._coordenate[1];
		return *this;
	}

	CPoint& operator/= (const double& p){
		_coordenate[0] /= p;
		_coordenate[1] /= p;
		return *this;
	}


	CPoint operator - (const CPoint& p){
		return CPoint (_coordenate[0] - p._coordenate[0], _coordenate[1] - p._coordenate[1]);
	}


	double distancia_euclideana (const CPoint& _p){
		double res = (_coordenate[0] - _p._coordenate[0]) * (_coordenate[0] - _p._coordenate[0]);
		res += (_coordenate[1] - _p._coordenate[1]) * (_coordenate[1] - _p._coordenate[1]);
		return sqrt(res);
	}


	CPoint operator * (const CPoint& p){
		return CPoint (_coordenate[0] * p._coordenate[0], _coordenate[1] * p._coordenate[1]);
	}

	void round () {
		_coordenate[0] = floor(_coordenate[0] + .5);
		_coordenate[1] = floor(_coordenate[1] + .5);
	}

	CPoint operator * (const double& p){
		return CPoint (_coordenate[0] * p, _coordenate[1] * p);
	}

	CPoint operator + (const double& p){
		return CPoint (_coordenate[0] + p, _coordenate[1] + p);
	}

	CPoint operator / (const double& p){
		return CPoint (_coordenate[0] / p, _coordenate[1] / p);
	}

	CPoint normalization (int n) {
		return CPoint (n / _coordenate[0], n / _coordenate[1]);
	}

	long double norma (){
		return  sqrt(_coordenate[0] * _coordenate[0] + _coordenate[1] * _coordenate[1]);
	}

	value_t& operator[] (const int& __pos){
		try{
			if (__pos > _SIZE) throw __pos % _SIZE;
			if (__pos < 0) throw (-1 * __pos) % _SIZE;
			else return _coordenate[__pos];
		} catch (int __new_pos) {
			return _coordenate[__new_pos];
		}
	}
	
	template <typename __TO>
	friend ostream& operator<< (ostream& out, const CPoint<__TO>& __point){
		out << __point._coordenate[X] << ", " << __point._coordenate[Y];
		return out;
	}
	
};


#endif